#include "common.h"
extern Client clients[CLIENT_MAX];
CheckData check_data;
/**
 * 定义需要解析结构体的对应关系表
 */
reflect_item_t json_struct_ref_tb[] = {
    _property_int(JsonStruct, oders),
    _property_int(JsonStruct, id),
    _property_int(JsonStruct, l_food),
    _property_int(JsonStruct, r_food),
    _property_int(JsonStruct, l_water),
    _property_int(JsonStruct, r_water),
    _property_int(JsonStruct, happy),
    _property_int(JsonStruct, temperature),
    _property_int(JsonStruct, humidity),
    _property_string(JsonStruct, c_date),
    _property_int(JsonStruct, entrust),
    _property_end()};

/**
    @brief 接收数据并处理函数实现
    @param __fd 监听文件描述符
    @param sql_ptr MYSQL指针
*/
int stm32_qt_recv(int __fd, MYSQL *sql_ptr)
{
    char __ptr[1024];
    int iRet = recv(__fd, __ptr, BUF_SIZE, 0);
    if (iRet <= 0)
        return iRet;
    printf("---- %s --- %d字节数据 ----\r\n", __func__, iRet);
    // 解析buf的json字符串
    /*const static char *tmp = "{\"oders\":\"asdasdasd\",\"id\":1,\"l_food\":123,\"r_food\":123,\"l_water\":123,\"r_water\":123,\"happy\":123,\"c_data\":\"asdasd\",\"entrust\":123}";
    csonJsonStr2Struct(tmp, &oder, json_struct_ref_tb);
    csonPrintProperty(&oder, json_struct_ref_tb);*/

    // 判断是stm32还是qt指令，执行相关命令
    oper_qt_stm32((const char *)__ptr, __fd, sql_ptr);

    return iRet;
}

/**
 * @brief 判断是qt客户端还是stm32客户端
 * @param __fd 客户端文件描述符
 * @return 1为qt，2为stm32
 */
int isStm32OrQtClient(int __fd)
{
    char buf[BUF_SIZE];
    memset(buf, 0, BUF_SIZE);

    if (-1 != recv(__fd, buf, BUF_SIZE, 0))
    {
        /*if (strncmp(buf, "1", 1) != 0 || strncmp(buf, "2", 1) != 0)
        {
            printf("---- 客户端第一次链接发送验证失败 ----\r\n %s \r\n", buf);
            // send(__fd, &buf, 1, 0);
            return -1;
        }*/
        if (-1 != send(__fd, buf, BUF_SIZE, 0))
            printf("%s 接收到的数据为: %s\n", __func__, buf);

        if (atoi(buf) == STM32 || strncmp(buf, "FF", 2) == 0 || strncmp(buf, "AT", 2) == 0)
        {
            return STM32;
        }
        else if (atoi(buf) == QT)
        {
            return QT;
        }
        else
        {
            return NOMOD;
        }
    }
}

/**
 * @brief 解析json 判断是哪个客户端指令并执行相对响应
 * @param __jsonStr json数据
 * @param __fd 文件描述符
 * @param sql_ptr MYSQL指针
 */
void oper_qt_stm32(const char *__jsonStr, int __fd, MYSQL *sql_ptr)
{
    JsonStruct oder;

    // 根据文件描述符拿到相应的客户端
    printf("---- %s  __fd is %d ----\r\n", __func__, __fd);
    if (stm32OrQt(__fd) == QT) //
    {
        // 解析json拿到数据
        csonJsonStr2Struct(__jsonStr, &oder, json_struct_ref_tb);
        csonPrintProperty(&oder, json_struct_ref_tb);

        /**
         * 向stm32发送添食指令
         */
        int stm32Fd = isStm32Login();
        switch (oder.oders)
        {
        /**
         *  开机发送数据
         * */
        case ON:
        {
            /* 去数据库查询数据 */
            printf("----------ON 进入----------\r\n");
            char *resJson = NULL;
            myMysql_select(sql_ptr, &resJson, &oder);
            printf("----------ON 退出----------\r\n");
            // 发送转换好的json数组
            send(__fd, resJson, strlen(resJson), 0);
            break;
        }
            // 通知stm32做操作

        case ADD_WATER:
        {
            if (1 == oper_stm32_water(stm32Fd))
                printf("---- %s 执行了,已启动喂水程序 ----\r\n", __func__);
            else
                printf("---- %s 执行了,喂水程序出错 ----\r\n", __func__);
            break;
        }
        case ADD_FOOD:
        {
            if (1 == oper_stm32_food(stm32Fd))
                printf("---- %s 执行了,已启动喂食程序 send to %d ----\r\n", __func__, stm32Fd);
            else
                printf("---- %s 执行了,喂食程序出错 %d ----\r\n", __func__, stm32Fd);
            break;
        }
        default:
            printf("未知的命令\r\n");
            break;
        }

        // 最后释放json指针
        csonFreePointer(&oder, json_struct_ref_tb);
    }
    else if (stm32OrQt(__fd) == STM32) // 此为stm32的客户端
    {
        char __tmpStm32[BUF_SIZE];
        memset(__tmpStm32, 0, sizeof(__tmpStm32));
        strncpy(__tmpStm32, __jsonStr, strlen(__jsonStr));
        printf("---- %s 接收到STM32的数据为: %s ----\r\n", __func__, __tmpStm32);
        int l_water = subStm32Str(__tmpStm32, 2, 4);
        int r_water = subStm32Str(__tmpStm32, 6, 4);
        int l_food = subStm32Str(__tmpStm32, 10, 4);
        int r_food = subStm32Str(__tmpStm32, 14, 4);
        int temperature = subStm32Str(__tmpStm32, 18, 4);
        int humidity = subStm32Str(__tmpStm32, 22, 4);
        /**
         * 校验当前数据相较于上次是否有改变
         */

        if (
            (l_water > check_data.l_water - 10 && l_water < check_data.l_water + 10) ||
            (r_water > check_data.r_water - 10 && r_water < check_data.r_water + 10) ||
            (l_food > check_data.l_food - 10 && l_food < check_data.l_food + 10) ||
            (r_food > check_data.r_food - 10 && r_food < check_data.r_food + 10))
        {
            if (check_data.temperature == temperature || check_data.humidity == humidity)
            {
                printf("---- 重量与温湿度都未改变，不操作数据库 ----\r\n");
                return;
            }
            check_data.temperature = temperature;
            check_data.humidity = humidity;
            if (EXIT_SUCCESS != updateTandH(sql_ptr))
                printf("---- 检查之前值不变之后，更新温湿度失败 ----\r\n");
            else
                printf("---- 检查之前值不变之后，更新温湿度成功 ----\r\n");
            return;
        }
        check_data.l_food = l_food;
        check_data.r_food = r_food;
        check_data.l_water = l_water;
        check_data.r_water = r_water;
        check_data.temperature = temperature;
        check_data.humidity = humidity;
        char insert_sql[BUF_SIZE] = {0};
        sprintf(insert_sql, INSERT_SQL, l_food, r_food, l_water, r_water, temperature, humidity);
        printf("---- %s : %s -----\n", __func__, insert_sql);
        if (EXIT_SUCCESS == myMysql_execute(sql_ptr, insert_sql))
        {
            printf("---- %s 执行执行插入STM32数据成功 ----\r\n", __func__);
        }
    }
    else
    {
        if (-1 != send(__fd, __jsonStr, strlen(__jsonStr), 0))
        {
            printf("---- else 发送成功！----\r\n");
        }
    }
}

/**
 * @brief stm32发送添食物指令
 * @param __fd 文件描述符
 * @return 0为出错，非零为正确
 */
int oper_stm32_food(int __fd)
{
    int flag = -1;
    char stm32_buf[BUF_SIZE];
    memset(stm32_buf, 0, BUF_SIZE);
    sprintf(stm32_buf, "2");
    if (-1 != send(__fd, stm32_buf, BUF_SIZE, 0))
        flag = 1;
    return flag;
}

/**
 * @brief stm32发送添食物指令
 * @param __fd 文件描述符
 * @return 0为出错，非零为正确
 */
int oper_stm32_water(int __fd)
{
    int flag = -1;
    char stm32_buf[BUF_SIZE];
    memset(stm32_buf, 0, BUF_SIZE);
    sprintf(stm32_buf, "1");
    if (-1 != send(__fd, stm32_buf, BUF_SIZE, 0))
        flag = 1;
    return flag;
}

/**
 * @brief 判断stm32是否登录
 * @return  未登录为 -1 登录成功为对应的文件描述符
 */
int isStm32Login()
{
    int i = 0, stm32Fd = -1;
    for (; i < CLIENT_MAX; i++)
    {
        if (clients[i].clientType == STM32)
        {
            stm32Fd = clients[i].clientFd;
            printf("---- %s STM32 FD IS %d ----\r\n", __func__, stm32Fd);
            break;
        }
    }
    return stm32Fd;
}

/**
 * @brief 判断该fd是stm32还是QT
 * @return 1为QT 2为stm32
 */
int stm32OrQt(int __fd)
{
    int i = 0;
    for (; i < CLIENT_MAX; i++)
    {
        if (clients[i].clientFd == __fd)
        {
            return clients[i].clientType;
        }
    }
}

/**
 * @brief 返回stm32或者qt的文件描述符
 * @return 1为QT 2为stm32
 */
int retSTM32orQtFd(int flag)
{
    int i = 0;
    for (; i < CLIENT_MAX; i++)
    {
        if (clients[i].clientType == flag)
        {
            return clients[i].clientFd;
        }
    }
}

/**
 * @brief 截取字符串
 * @param str 截取的字符串
 * @param begin 在字符串中的截取的起始下标
 * @param len 截取的长度
 */
int subStm32Str(char *str, int begin, int len)
{
    int i = 0;
    char tmp[32] = {0};
    for (; i < len; i++)
    {
        if (str[begin] != '\0')
        {
            tmp[i] = str[begin];
            begin++;
        }
    }
    tmp[i] = '\0';
    return atoi(tmp);
}
